import org.antlr.v4.runtime.tree.ParseTreeProperty;

public class RefPhase extends CymbolBaseListener {

    ParseTreeProperty<Scope> scopes = new ParseTreeProperty<Scope>();
    GlobalScope global;
    Scope currentScope;

    public RefPhase(GlobalScope globals, ParseTreeProperty<Scope> scopes) {
        this.global = globals;
        this.scopes = scopes;
    }
    public void enterFile(CymbolParser.FileContext ctx) {
        this.currentScope = this.global;
    }
    public void enterFunctionDecl(CymbolParser.FunctionDeclContext ctx) {
        this.currentScope = scopes.get(ctx);
    }
    public void exitFunctionDecl(CymbolParser.FunctionDeclContext ctx) {
        this.currentScope = this.currentScope.getEnclosingScope();
    }
    public void enterBlock(CymbolParser.BlockContext ctx) {
        this.currentScope = scopes.get(ctx);
    }
    public void exitBlock(CymbolParser.BlockContext ctx) {
        this.currentScope = this.currentScope.getEnclosingScope();
    }
    public void exitVar(CymbolParser.VarContext ctx) {
        String name = ctx.ID().getSymbol().getText();
        Symbol var = this.currentScope.resolve(name);
        if (var == null) {
            CheckSymbols.error(ctx.ID().getSymbol(), "no such variable: " + name);
        }
        if (var instanceof FunctionSymbol) {
            CheckSymbols.error(ctx.ID().getSymbol(), name + " is not a variable");
        }
    }
    public void exitCall(CymbolParser.CallContext ctx) {
        String name = ctx.ID().getText();
        Symbol function = this.currentScope.resolve(name);
        if (function == null) {
            CheckSymbols.error(ctx.ID().getSymbol(), "no such function: " + name);
        }
        if (function instanceof VariableSymbol) {
            CheckSymbols.error(ctx.ID().getSymbol(), name + " is not a function");
        }
    }

}
